package com.jdrx.sw.sewage.service.common;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jdrx.platform.commons.rest.beans.vo.ResponseVO;
import com.jdrx.platform.commons.rest.exception.BizException;
import com.jdrx.platform.commons.rest.factory.ResponseFactory2;
import com.jdrx.sw.sewage.beans.entity.StationWaterQualityPO;
import com.jdrx.sw.sewage.beans.mq.IOTCommandStatus;
import com.jdrx.sw.sewage.beans.vo.StationVO;
import com.jdrx.sw.sewage.common.constant.Constant;
import com.jdrx.sw.sewage.common.enums.ECommandStatus;
import com.jdrx.sw.sewage.common.enums.InOutType;
import com.jdrx.sw.sewage.common.util.LocalDateTimeUtils;
import com.jdrx.sw.sewage.dao.StationDAO;
import com.jdrx.sw.sewage.dao.StationWaterQualityDAO;
import com.jdrx.sw.sewage.service.base.BaseServiceImpl;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;

import static com.jdrx.sw.sewage.common.constant.Constant.*;

@Service
public class CommandService extends BaseServiceImpl {

    public static final Logger logger = LoggerFactory.getLogger(CommandService.class);
    @Autowired
    private RedisService redisService;
    @Autowired
    private SequenceDefineServiceImpl sequenceDefineServiceImpl;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private StationWaterQualityDAO stationWaterQualityDAO;
    @Autowired
    private StationDAO stationDAO;

    /**
     * 处理物联网命令参数
     * 命令参数格式
     * {"tenantId":"168","id":"030003000002","sn":"300220041782","time":"2021-02-07 15:08:31","describe":"命令执行完成","type":0,"tid":"28","gateway":"300220041782","status":5}
     *
     * @param map
     */
    public void handleCommandData(IOTCommandStatus map) throws BizException {
        String tid = map.getTid();
        if (StringUtils.isEmpty(tid)) {
            logger.debug("tid为空，不处理命令回执", tid);
            return;
        }
        if (null != map.getMessage()) redisService.setJson(COMMAND_KEY + tid, map, null);

        if (ECommandStatus.CMD_EXECUTE_SUCCESS.getKey().equals(map.getStatus()) && !map.getMessage().isEmpty()) {
            String tenantId = map.getTenantId();
            String dataNode = null;
            if (StringUtils.isNotEmpty(tenantId)) {
                Map<String, Object> mget = redisService.mget(REDIS_TENANT + tenantId, Object.class);
                if (null == mget) {
                    logger.debug("未找到该租户id={}的dataNode,不处理告警", tenantId);
                    return;
                }
                Map<String, Object> dataNodeMap = (Map<String, Object>) JSON.parse((String) mget.get("dataNode"));
                dataNode = dataNodeMap.get(Constant.APPLICATION_NAME) + "";
                if (StringUtils.isBlank(dataNode) || dataNode.equals("null")) {
                    logger.debug("该dataNode={}为空,不处理告警", dataNode);
                    return;
                }
                dataNode = getSQLPerfix(dataNode);
            }

            StationVO stationVO = stationDAO.selectStationByNetNum(map.getSn(), dataNode);
            if (Objects.isNull(stationVO)) {
                logger.debug("该网关对应的站点不存在", map.getSn());
                return;
            }

            List<Map<String, Object>> messages = map.getMessage();
            String tidStr = COMMAND_KEY_DATA + map.getTid();
            String date = redisService.getStr(tidStr);

            StationWaterQualityPO waterQualityPOJS = new StationWaterQualityPO();
            StationWaterQualityPO waterQualityPOCS = new StationWaterQualityPO();
            LocalDateTime localDateTime = LocalDateTimeUtils.dataToLocalDate(Long.valueOf(date));
            Long stationId = stationVO.getId();
            waterQualityPOJS.setCreateTime(localDateTime);
            waterQualityPOJS.setStationId(stationId);
            waterQualityPOCS.setCreateTime(localDateTime);
            waterQualityPOCS.setStationId(stationId);

            for (int i = 0, len = messages.size(); i < len; i++) {
                Map<String, Object> dataMap = messages.get(i);
                if (MapUtils.isEmpty(dataMap)) {
                    logger.debug("messages没有数据,不处理命令拉取回执！");
                    redisService.del(tidStr);
                    continue;
                }

                String key = MapUtils.getString(dataMap, "key");
                Double vaStr = MapUtils.getDouble(dataMap, "val");
                String[] keys = key.split("_");
                String gy = keys[0];
                String point = keys[2];
                if (JSK.equals(gy)) {
                    waterQualityPOJS.setInOut(InOutType.IN.getKey());
                    encapsulationCommPoint(waterQualityPOJS, vaStr, point);
                }
                if (CSQ.equals(gy)) {
                    waterQualityPOCS.setInOut(InOutType.OUT.getKey());
                    encapsulationCommPoint(waterQualityPOCS, vaStr, point);
                }
            }

            StationWaterQualityPO poJS = stationWaterQualityDAO.findByStationIdAndTimeAndInOut(InOutType.IN.getKey(), stationId, localDateTime, dataNode);
            StationWaterQualityPO poCS = stationWaterQualityDAO.findByStationIdAndTimeAndInOut(InOutType.OUT.getKey(), stationId, localDateTime, dataNode);
            List<StationWaterQualityPO> datas = Lists.newArrayList();
            if (Objects.isNull(poJS) && null != waterQualityPOJS.getInOut()) {
                datas.add(waterQualityPOJS);
            } else if (!Objects.isNull(poJS) && null != poJS.getId() && waterQualityPOJS.isEmptyJudge(waterQualityPOJS)) {
                logger.debug("进水口数据id:" + poJS.getId() + "和已存在的进水对象：" + poJS);
                waterQualityPOJS.setId(poJS.getId());
                waterQualityPOJS.setDataNode(dataNode);
                stationWaterQualityDAO.updateById(waterQualityPOJS);
                redisService.del(tidStr);
            }

            if (Objects.isNull(poCS) && null != waterQualityPOCS.getInOut()) {
                datas.add(waterQualityPOCS);
            } else if (!Objects.isNull(poCS) && null != poCS.getId() && waterQualityPOCS.isEmptyJudge(waterQualityPOCS)) {
                logger.debug("进水口数据id:" + poCS.getId() + "和已存在的进水对象：" + poCS);
                waterQualityPOCS.setDataNode(dataNode);
                waterQualityPOCS.setId(poCS.getId());
                stationWaterQualityDAO.updateById(waterQualityPOCS);
                redisService.del(tidStr);
            }

            if (datas.size() > 0) {
                logger.debug("新增数据list：" + datas);
                Map<String, Object> params = Maps.newHashMap();
                params.put("list", datas);
                params.put("dataNode", dataNode);
                stationWaterQualityDAO.batchInsert(params);
                redisService.del(tidStr);
            }
        }
    }

    /**
     * 下发拉取数据命令
     *
     * @param
     * @throws BizException
     */
    public ResponseVO CommandLssuePullData(String iotGatewayNum, Date date, List<String> points, String dataNode) {
        //调用物联网远程服务
        try {
            Map<String, Object> map = new HashMap<>();
            map.put("sn", iotGatewayNum);
            long tid = sequenceDefineServiceImpl.increment(DEVICE_COMMAND_NUM, dataNode);
            map.put("tid", tid);
            map.put("time", date);
            map.put("executeMethod", "READ_PARAMS_VALUE_FANYI");

            Map<String, Object> par = new HashMap<>();
            par.put("points", points);
            map.put("params", par);

            //发送mq，然后等结果
            rocketMQTemplate.convertAndSend("iot-fanyi-command-put-smart", map);
            redisService.set(COMMAND_KEY_DATA + tid, date.getTime(), 3600L);//3600秒失效
//        String result = waitCommandResult(tid);
//        if (!TRUE_STR.equals(result)) return ResponseFactory2.err(result);
        } catch (BizException e) {
            logger.error(iotGatewayNum + "拉取数据命令下发失败！");
            e.printStackTrace();
        }
        return ResponseFactory2.ok();
    }

    /**
     * 等待命令返回结果
     *
     * @param tid
     * @throws BizException
     */
    public String waitCommandResult(long tid) throws BizException, InterruptedException {
        String redisQueryKey = COMMAND_KEY + tid;
        // 循环等待返回命令
        while (true) {
            IOTCommandStatus iotCommandStatus = redisService.getJson(redisQueryKey, IOTCommandStatus.class);
            // 判断状态
            if (!Objects.isNull(iotCommandStatus)) {
                Integer status = iotCommandStatus.getStatus();
                if (ECommandStatus.CMD_EXECUTE_SUCCESS.getKey().equals(status)) {
                    redisService.del(redisQueryKey);
                    return TRUE_STR;
                } else if (!ECommandStatus.CMD_WAITING_TO_SEND.getKey().equals(status)
                        && !ECommandStatus.CMD_SEND_IN_PROGRESS.getKey().equals(status)
                        && !ECommandStatus.CMD_SEND_TO_DEVICE.getKey().equals(status)) {
                    String name = ECommandStatus.getName(status);
                    if (StringUtils.isBlank(name)) throw new BizException("物联网返回状态有误[{}]", name);
                    redisService.del(redisQueryKey);
                    return name;
                }
            }
            Thread.sleep(1000);
        }
    }

    private void encapsulationCommPoint(StationWaterQualityPO waterQualityPO, Double vaStr, String point) {
        if (COD.equals(point)) waterQualityPO.setCod(vaStr);
        if (NH3N.equals(point)) waterQualityPO.setNh3n(vaStr);
        if (TN.equals(point)) waterQualityPO.setTn(vaStr);
        if (PH.equals(point)) waterQualityPO.setPh(vaStr);
        if (TP.equals(point)) waterQualityPO.setTp(vaStr);
        if (SS.equals(point)) waterQualityPO.setSs(vaStr);
        if (WD.equals(point)) waterQualityPO.setTemperature(vaStr);
    }
}
